///////////////////////////////////////////////////
// 
function gewUITheme()
{
  // Label
  this.labelFont = null;
  // Button
  this.buttonFont = null;
  this.buttonNormalImg = null;
  this.buttonClickedImg = null;
  this.buttonOverImg = null;
  // Menu
  this.menuFont = null;
  this.menuItemSpace = 5;
  this.menuHeight = 20;
  this.menuSubItemVerticalSpace = 10;
  this.menuSubItemHorizontalSpace = 10;
  
  this.menuBkgImg = null;
  this.menuItemHightLightImg = null;
  this.menuItemListBkgImg = null;
  //Dialog
  this.dialogFont = null;
  this.dialogTitleSize = 20;
  this.dialogBorderSize = 5;
  this.dialogBorderImg = null;
  this.dialogBkgImg = null; 
}

///////////////////////////////////////////////////
// Class gewUIView
//  This is the base class for all UI element
function gewUIView(parent)
{
  this.parent = parent;
  this.children = [];  
  this.localX = 0;
  this.localY = 0;
  this.name = null ;
  // Event handler
  this.onMouseDown = null;
  this.onMouseUp = null;
  this.onMouseOver = null;
  this.onMouseOut  = null;
  this.onMouseMove = null;
  this.onKeyDown = null;
  this.onKeyUp = null; 
  // PRIVATE :  
  this.isVisible = true;
  this.canvasX = 0;
  this.canvasY = 0;
  this.width = 0;
  this.height = 0;
  this.isMouseOn = false;
  if(parent)
  {
    parent.children.push(this);
    this.scene2d = parent.scene2d;
    this.depth  = parent.depth+10;
    this.theme = parent.theme;
  }
  else
  {
    this.depth = 0;
    this.theme = null;
  } 
  this.updateLayout();
}

gewUIView.prototype = {
  getByName:function(name)
  {
    if(this.name.localeCompare(name)==0)
      return this;
    var children = this.children;
    var childNum = children.length;
    for(var i =0;i <childNum;i++)
    {
      var view = children[i].getByName(name);
      if(view)
        return view;
    }
    return null;
  },
  dispatchMouseDown : function(e)
  {
    var children = this.children;
    var childNum = children.length;
    var isAbsorbed = false;
    for(var i =0;i <childNum;i++)
    {
      var uiview = children[i];
      if(!uiview.isVisible)
        continue;
      if( isInRect(e.canvasX,e.canvasY, uiview.canvasX, uiview.canvasY,uiview.width,uiview.height) )
      {
        isAbsorbed = uiview.dispatchMouseDown(e);
        if(isAbsorbed==true)
          return true;
      }
    }
    if(this.defaultMouseDownBehavior)
      this.defaultMouseDownBehavior(e);
    if(this.onMouseDown)
      return this.onMouseDown(e);
    else
      return false;
  },
  dispatchMouseUp : function(e)
  {
    var children = this.children;
    var childNum = children.length;
    var isAbsorbed = false;
    for(var i =0;i <childNum;i++)
    {
      var uiview = children[i];
      if(!uiview.isVisible)
        continue;
      if( isInRect(e.canvasX,e.canvasY, uiview.canvasX, uiview.canvasY,uiview.width,uiview.height) )
      {
        isAbsorbed = uiview.dispatchMouseUp(e);
        if(isAbsorbed==true)
          return true;
      }
    }
    if(this.defaultMouseUpBehavior)
      this.defaultMouseUpBehavior(e);
    if(this.onMouseUp)
      return this.onMouseUp(e);
    else
      return false;
  },
  dispatchMouseMove: function(e)
  {
    var children = this.children;
    var childNum = children.length;
    var isAbsorbed = false;
    for(var i =0;i <childNum;i++)
    {
      var uiview = children[i];
      if(!uiview.isVisible)
        continue;
      var isLastFrameMouseOn = uiview.isMouseOn;
      var isCurrentMouseOn = isInRect(e.canvasX,e.canvasY, uiview.canvasX, uiview.canvasY,uiview.width,uiview.height);
      uiview.isMouseOn = isCurrentMouseOn;
      if(isLastFrameMouseOn&& !isCurrentMouseOn)
      {
        if(uiview.defaultMouseOutBehavior)
          uiview.defaultMouseOutBehavior(e);
        if(uiview.onMouseOut)
          uiview.onMouseOut(e);
        isAbsorbed = uiview.dispatchMouseMove(e);
        if(isAbsorbed)
          return true;
      }
      else if(!isLastFrameMouseOn&&isCurrentMouseOn )
      {
        if(uiview.defaultMouseOverBehavior)
          uiview.defaultMouseOverBehavior(e);
        if(uiview.onMouseOver)
          uiview.onMouseOver(e);
        isAbsorbed = uiview.dispatchMouseMove(e);
        if(isAbsorbed)
          return true;
      }
      else if(isCurrentMouseOn)
      {
        isAbsorbed = uiview.dispatchMouseMove(e);
        if(isAbsorbed)
          return true;
      }
    }
    if(this.defaultMouseMoveBehavior)
      this.defaultMouseMoveBehavior(e);
    if(this.onMouseMove)
      return this.onMouseMove(e);
  },
  updateLayout : function()
  {
    var parent = this.parent;
    if(parent)
    {
      this.canvasX = parent.canvasX+this.localX;
      this.canvasY = parent.canvasY+this.localY;
    }
    else
    {
      this.canvasX = this.localX;
      this.canvasY = this.localY;
    }
    var children = this.children;
    var childNum = children.length;
    for(var i =0;i <childNum;i++)
    {
      children[i].setPosition(children[i].localX,children[i].localY);
    }
  },
  setPosition: function(x,y)
  {
    this.localX = x;
    this.localY = y; 
    this.updateLayout();
  },
  setVisible: function(visible)
  {
    if(this.isVisible!=visible)
    {
      this.isVisible = visible;
      var children = this.children;
      var childNum = children.length;
      for(var i =0;i <childNum;i++)
      {
        children[i].setVisible(visible);
      }
    }
  }
}

///////////////////////////////////////////////////
// Class gewUIImage
//  This UI display an image
function gewUIImage(parent,x,y,w,h,imageName)
{
  gewUIView.call(this,parent);
  this.sprite = new gewSprite2D();
  if(x!= undefined && y!=undefined)
    this.setPosition(x,y);
  if(w!=undefined&&h != undefined)
    this.setSize(w,h);
  if(imageName)
    this.setImage(imageName);
  this.sprite.setDepth(this.depth);
  this.scene2d.layer0.insert(this.sprite);
}
extend2(gewUIImage, gewUIView);
gewUIImage.prototype.setPosition = function(x,y)
{
  gewUIView.prototype.setPosition.call(this,x,y);
  this.sprite.setPosition(this.canvasX,this.canvasY);
}
gewUIImage.prototype.setSize = function(w,h)
{
  this.width = w;
  this.height = h;
  this.sprite.setAsRectangle(w,h);
}
gewUIImage.prototype.setImage = function(imageName)
{
  this.sprite.setSubTexture(imageName);
}
gewUIImage.prototype.setVisible = function(visible)
{
  gewUIView.prototype.setVisible.call(this,visible);
  this.sprite.setVisible(visible);
}

///////////////////////////////////////////////////
// Class gewUILabel
//  This UI display a string
function gewUILabel(parent,content,font)
{
  gewUIView.call(this,parent);
  this.sprites = [];
  if(font)
    this.font = font;
  else
    this.font = this.theme.labelFont;
  if(content)
    this.setContent(content);
  else
    this.content = "";
}
extend2(gewUILabel, gewUIView);
gewUILabel.prototype.setPosition = function(x,y)
{
  var oldCanvasX = this.canvasX;
  var oldCanvasY = this.canvasY;
  gewUIView.prototype.setPosition.call(this,x,y);
  var dx = this.canvasX-oldCanvasX;
  var dy = this.canvasY-oldCanvasY;
  var sprites = this.sprites;
  var num = sprites.length;
  for(var i=0;i<num;i++)
  {
    var s = sprites[i];
    s.setPosition(s.translate.x+dx,s.translate.y+dy);  
  }
}
gewUILabel.prototype.setContent = function(content)
{
  this.clearContent()
  this.content = content;
  var font = this.font;
  font.generateSprites(this.scene2d.layer0,this.sprites, content, this.canvasX,this.canvasY, this.width, this.height, this.depth);
  if(this.isVisible==false)
  {
    var sprites = this.sprites;
    var len = sprites.length;
    for(var i=0;i<len;i++)
    {
      sprites[i].setVisible(false);
    }
  }
  this.width = font.getStringWidth(content);
  this.height = font.lineHeight;
}
gewUILabel.prototype.clearContent = function()
{
  this.content = "";
  var sprites = this.sprites;
  var len = sprites.length;
  var layer = this.scene2d.layer0;
  for(var i=0;i<len;i++)
  {
    layer.remove(sprites[i]);
    delete sprites[i];
  }
}
gewUILabel.prototype.setVisible = function(visible)
{
  gewUIView.prototype.setVisible.call(this,visible);
  var sprites = this.sprites;
  var len = sprites.length;
  for(var i=0;i<len;i++)
  {
    sprites[i].setVisible(visible);
  }
}

///////////////////////////////////////////////////
// Class gewUIButton
//  This UI display a button
function gewUIButton(parent,caption,x,y,w,h)
{
  gewUIView.call(this,parent);
  this.sprite = new gewSprite2D();
  this.setPosition(x,y);
  this.setSize(w,h);
  var font = this.theme.buttonFont
  this.label = new gewUILabel(this,"",font);
  var captionWidth = font.getStringWidth(caption);
  var labelX = w/2 - captionWidth/2;
  var labelY = h/2 - font.lineHeight/2;
  this.label.setPosition(labelX,labelY);
  this.label.depth = this.depth+1;
  this.label.setContent(caption);
  var theme = this.theme;
  this.normalImageName = theme.buttonNormalImg;
  this.overImageName = theme.buttonOverImg;
  this.clickedImageName = theme.buttonClickedImg;
  this.sprite.setSubTexture(this.normalImageName);
  this.sprite.setDepth(this.depth);
  this.scene2d.layer0.insert(this.sprite);
}
extend2(gewUIButton, gewUIView);
gewUIButton.prototype.defaultMouseOverBehavior = function(e)
{
  if(this.overImageName)
    this.sprite.setSubTexture(this.overImageName)
}
gewUIButton.prototype.defaultMouseOutBehavior = function(e)
{
  this.sprite.setSubTexture(this.normalImageName)
}
gewUIButton.prototype.defaultMouseDownBehavior = function(e)
{
  if(this.clickedImageName)
    this.sprite.setSubTexture(this.clickedImageName)
}
gewUIButton.prototype.defaultMouseUpBehavior = function(e)
{
  this.sprite.setSubTexture(this.normalImageName)
}
gewUIButton.prototype.setPosition = function(x,y)
{
  gewUIView.prototype.setPosition.call(this,x,y);
  this.sprite.setPosition(this.canvasX,this.canvasY);
}
gewUIButton.prototype.setSize = function(w,h)
{
  this.width = w;
  this.height = h;
  this.sprite.setAsRectangle(w,h);
}
gewUIButton.prototype.setVisible = function(visible)
{
  gewUIView.prototype.setVisible.call(this,visible);
  this.sprite.setVisible(visible);
}

///////////////////////////////////////////////////
// Class gewUIMenu
//  This UI display an image
function gewUIMenu(parent)
{
  gewUIView.call(this,parent);
  this.sprite = new gewSprite2D();
  this.width = this.scene2d.canvasHalfSize[0]*2;
  this.height = this.scene2d.canvasHalfSize[1]*2;
  this.realHeight = this.theme.menuHeight;
  this.setPosition(0,0);
  this.sprite.setAsRectangle(this.width,this.realHeight);
  this.sprite.setSubTexture(this.theme.menuBkgImg);
  this.sprite.setDepth(this.depth);
  this.scene2d.layer0.insert(this.sprite);
  this.items = {};
  // Private:
  this.mainMenu = this;
  this.activeSubMenu = null; 
  this.offset = 0;
  this.itemSpace = this.theme.menuItemSpace;
}
extend2(gewUIMenu, gewUIView);
gewUIMenu.prototype.addItem = function(name)
{
  var itemWidth = this.theme.menuFont.getStringWidth(name)+ 2*this.itemSpace;
  this.items[name] =new gewUISubMenu(this,name,this.offset,0,itemWidth,this.realHeight);
  this.offset+=itemWidth
}
gewUIMenu.prototype.setPosition = function(x,y)
{
  gewUIView.prototype.setPosition.call(this,x,y);
  this.sprite.setPosition(this.canvasX,this.canvasY);
}
gewUIMenu.prototype.setVisible = function(visible)
{
  gewUIView.prototype.setVisible.call(this,visible);
  this.sprite.setVisible(visible);
}
gewUIMenu.prototype.defaultMouseUpBehavior = function(e)
{
  if(this.mainMenu.activeSubMenu)
  {
    var uiview = this.mainMenu.activeSubMenu; 
    if( !isInRect(e.canvasX,e.canvasY,uiview.canvasX,uiview.canvasY,uiview.width,uiview.height))
      this.mainMenu.activeSubMenu.hideList();
  }
}
///////////////////////////////////////////////////
// Class gewUISubMenu
//  This UI display a submenu of menu
function gewUISubMenu(parent,name,x,y,w,h)
{
  gewUIView.call(this,parent);
  this.mainMenu = parent.mainMenu;
  this.setPosition(x,y);
  this.width = w;
  this.height = h;
  var font = this.theme.menuFont;
  this.label = new gewUILabel(this,name,font);
  this.label.depth = this.parent.depth+2;
  var captionWidth = font.getStringWidth(name);
  var labelX = w/2 - captionWidth/2;
  var labelY = h/2 - font.lineHeight/2;
  this.label.setPosition(labelX,labelY);
  
  var hlsprite = this.hightLightSprite = new gewSprite2D();
  hlsprite.setAsRectangle(w,h);
  hlsprite.setPosition(this.canvasX,this.canvasY);
  hlsprite.setDepth(this.depth+1);
  hlsprite.setSubTexture(this.theme.menuItemHightLightImg);
  this.scene2d.layer0.insert(hlsprite);
  
  var bksprite = this.itemBkgSprite = new gewSprite2D();
  bksprite.setPosition(this.canvasX,this.canvasY+ this.mainMenu.realHeight+2);
  bksprite.setDepth(this.mainMenu.depth);
  bksprite.setSubTexture(this.theme.menuItemListBkgImg);
  this.scene2d.layer0.insert(bksprite);
  
  hlsprite.setVisible(false);
  bksprite.setVisible(false);
  this.items = {};
  this.offset = 0;
  this.maxSubItemWidth = 0;
}
extend2(gewUISubMenu, gewUIView);
gewUISubMenu.prototype.defaultMouseOverBehavior = function(e)
{
  this.hightLightSprite.setVisible(true);
}
gewUISubMenu.prototype.defaultMouseOutBehavior = function(e)
{
  this.hightLightSprite.setVisible(false);
  //this.itemBkgSprite.setVisible(false);
}
gewUISubMenu.prototype.defaultMouseUpBehavior = function(e)
{
  var items = this.items;
  var len = items.length;
  if(this.mainMenu.activeSubMenu)
  {
    this.mainMenu.activeSubMenu.hideList();
    this.mainMenu.activeSubMenu = null;
  }
  this.mainMenu.activeSubMenu = this;
  this.itemBkgSprite.setVisible(!this.itemBkgSprite.isVisible);
  for (var i in items)
  {
    items[i].setVisible(!items[i].isVisible);
  }
}
gewUISubMenu.prototype.addItem = function(name)
{  
  var font = this.theme.menuFont;
  var theme = this.theme;
  var itemWidth = font.getStringWidth(name)+ 2*theme.menuSubItemHorizontalSpace;
  if( itemWidth> this.maxSubItemWidth)
    this.maxSubItemWidth = itemWidth;
  this.offset+= (font.lineHeight+theme.menuSubItemVerticalSpace);
  var item =new gewUISubMenu(this.mainMenu,name,this.canvasX,this.offset,itemWidth,this.height);
  item.setVisible(false);
  this.items[name] = item;
  
  this.itemBkgSprite.setAsRectangle(this.maxSubItemWidth,this.offset );
}
gewUISubMenu.prototype.setPosition = function(x,y)
{
  gewUIView.prototype.setPosition.call(this,x,y);
}
gewUISubMenu.prototype.hideList = function()
{
  this.itemBkgSprite.setVisible(false);
  var items = this.items;
  for (var i in items)
  {
    items[i].setVisible(false);
  }  
}
gewUISubMenu.prototype.setVisible = function(visible)
{
  if( this.isVisible == visible)
    return;
  this.itemBkgSprite.setVisible(true);
  gewUIView.prototype.setVisible.call(this,visible);
  this.hightLightSprite.setVisible(false);
  var items = this.items;
  var len = items.length;
  for (var i in items)
  {
    items[i].setVisible(visible);
  }  
}

///////////////////////////////////////////////////
// Class gewUIDialog
//  This UI display an dialog
function gewUIDialog(parent,x,y,w,h,title)
{
  gewUIView.call(this,parent);
  var theme = this.theme;
  var bs = this.borderSprite = new gewSprite2D();
  bs.setDepth(this.depth);
  bs.setSubTexture(theme.dialogBorderImg);
  this.scene2d.layer0.insert(bs);
  
  this.borderSize = theme.dialogBorderSize;
  this.titleSize = theme.dialogTitleSize;
  var bkgs = this.bkgSprite = new gewSprite2D();
  bkgs.setDepth(this.depth+1);
  bkgs.setSubTexture(theme.dialogBkgImg);
  this.scene2d.layer0.insert(bkgs);
  
  var font = this.theme.dialogFont;
  this.title = new gewUILabel(this,"",font);
  var titleX = this.borderSize;
  var titleY = (this.titleSize - font.lineHeight)/2;
  this.title.setPosition(titleX,titleY);
  this.title.setContent(title);
  this.setPosition(x,y);
  this.setSize(w,h);
  this.isDrag = false;
}
extend2(gewUIDialog, gewUIView);
gewUIDialog.prototype.setPosition = function(x,y)
{
  gewUIView.prototype.setPosition.call(this,x,y);
  this.borderSprite.setPosition(this.canvasX,this.canvasY);
  this.bkgSprite.setPosition(this.canvasX+this.borderSize,this.canvasY+this.titleSize);
}
gewUIDialog.prototype.setSize = function(w,h)
{
  this.width = w;
  this.height = h;
  this.bkgSprite.setAsRectangle(w-2*this.borderSize,h-this.borderSize-this.titleSize);
  this.borderSprite.setAsRectangle(w,h);
}
gewUIDialog.prototype.setImage = function(imageName)
{
  this.sprite.setSubTexture(imageName);
}
gewUIDialog.prototype.setVisible = function(visible)
{
  gewUIView.prototype.setVisible.call(this,visible);
  this.sprite.setVisible(visible);
}

gewUIDialog.prototype.defaultMouseUpBehavior = function(e)
{
  this.isDrag = false;
}
gewUIDialog.prototype.defaultMouseDownBehavior = function(e)
{
  this.isDrag = true;
  this.startMouseX = e.canvasX;
  this.startMouseY = e.canvasY;
}
gewUIDialog.prototype.defaultMouseMoveBehavior = function(e)
{
  if(this.isDrag)
  {
    this.setPosition(this.localX+ (e.canvasX-this.startMouseX),this.localY+ (e.canvasY-this.startMouseY));
    this.startMouseX = e.canvasX;
    this.startMouseY = e.canvasY;
  }
}


